﻿//using SharpDepend.Datatypes;
//using System.Collections.Generic;
//using Windows.ApplicationModel.Core;
//using Windows.Graphics.Display;
//using Windows.UI.Core;
//using Windows.UI.Input;
//using Windows.UI.Xaml;
//using Windows.UI.Xaml.Input;

//namespace SharpDepend.WinRT
//{
//    public class MultiTouchManager : IMultiTouchManager
//    {
//        public IMultiTouch CreateMultiTouch<T>(T onUIElement, string tag)
//        {
//            return new MultiTouch((UIElement)(object)onUIElement, tag);
//        }
//    }

//    /// <summary>
//    /// Reference: http://stackoverflow.com/questions/28677538/global-pointer-based-touch-input-handling-regardless-of-uielement
//    /// </summary>
//    public class MultiTouch : IMultiTouch
//    {
//        private CoreWindow mCoreWindow;
//        private float mScaleFactor;

//        private static TouchCollection EmptyTouchCollection = new TouchCollection(new TouchLocation[0]);

//        private Dictionary<uint, TouchLocation> current = new Dictionary<uint, TouchLocation>();
//        private Dictionary<uint, bool> current_hasBeenStated = new Dictionary<uint, bool>();
//        private List<uint> s_releasedToRemove = new List<uint>();
//        private View mElement;
//        //private MovableTrackObject mMoveable;
//        private HashSet<uint> mMovingTouch;
//        private string mTag;

//        public MultiTouch(View element, string tag)
//        {
//            if (mCoreWindow == null)
//            {
//                mCoreWindow = CoreApplication.MainView.CoreWindow;
//                mCoreWindow.PointerPressed += mCoreWindow_PointerPressed;
//                mCoreWindow.PointerMoved += mCoreWindow_PointerMoved;
//                mCoreWindow.PointerReleased += mCoreWindow_PointerReleased;

//                //mDpi = DisplayInformation.GetForCurrentView().LogicalDpi;
//                ResolutionScale resolutionScale = DisplayInformation.GetForCurrentView().ResolutionScale;
//                mScaleFactor = (float)resolutionScale / 100.0f;
//            }

//            mMovingTouch = new HashSet<uint>();
//            mTag = tag;
//            mElement = element;
//        }

//        private int GetUniqueId()
//        {
//            bool isUnique = false;
//            int id = 0;
//            while (!isUnique)
//            {
//                bool equal = false;
//                foreach (var item in current)
//                {
//                    if (id == item.Value.ID)
//                    {
//                        id++;
//                        equal = true;
//                        break;
//                    }
//                }

//                if (!equal)
//                {
//                    break;
//                }
//            }

//            return id;
//        }

//        #region Touch.

//        void mCoreWindow_PointerPressed(CoreWindow sender, PointerEventArgs e)
//        {
//            lock (this)
//            {
//                Down(e);
//            }
//        }

//        private void Down(PointerEventArgs e)
//        {
//            var position = e.CurrentPoint.Position;

//            if (current.ContainsKey(e.CurrentPoint.PointerId))
//            {
//                // UPDATE.
//                TouchLocation touch = current[e.CurrentPoint.PointerId];
//                touch.X = position.X;
//                touch.Y = position.Y;
//                touch.State = TouchLocationState.Pressed;
//                current[e.CurrentPoint.PointerId] = touch;

//                if (!current_hasBeenStated.ContainsKey(e.CurrentPoint.PointerId))
//                {
//                    current_hasBeenStated.Add(e.CurrentPoint.PointerId, false);
//                }
//                else
//                {
//                    current_hasBeenStated[e.CurrentPoint.PointerId] = false;
//                }

//                mMovingTouch.Remove(e.CurrentPoint.PointerId);
//            }
//            else
//            {
//                // ADD.
//                current.Add(e.CurrentPoint.PointerId, new TouchLocation(GetUniqueId(), position.X, position.Y, TouchLocationState.Pressed));
//                current_hasBeenStated.Add(e.CurrentPoint.PointerId, false);
//            }
//        }

//        void mCoreWindow_PointerMoved(CoreWindow sender, PointerEventArgs e)
//        {
//            if (e.CurrentPoint.IsInContact)
//            {
//                TouchMove(e);
//            }
//        }

//        private void TouchMove(PointerEventArgs e)
//        {
//            var position = e.CurrentPoint.Position;

//            if (!current_hasBeenStated.ContainsKey(e.CurrentPoint.PointerId))
//            {
//                Down(e);
//            }

//            if (current_hasBeenStated[e.CurrentPoint.PointerId])
//            {
//                if (!mMovingTouch.Contains(e.CurrentPoint.PointerId))
//                {
//                    mMovingTouch.Add(e.CurrentPoint.PointerId);

//                    TouchLocation touch = current[e.CurrentPoint.PointerId];
//                    touch.X = position.X;
//                    touch.Y = position.Y;
//                    touch.State = TouchLocationState.Moved;
//                    current[e.CurrentPoint.PointerId] = touch;

//                    mMovingTouch.Remove(e.CurrentPoint.PointerId);
//                }
//            }
//        }

//        void mCoreWindow_PointerReleased(CoreWindow sender, PointerEventArgs e)
//        {
//            lock (this)
//            {
//                var position = e.CurrentPoint.Position;

//                TouchLocation touch = current[e.CurrentPoint.PointerId];
//                touch.X = position.X;
//                touch.Y = position.Y;
//                touch.State = TouchLocationState.Released;
//                current[e.CurrentPoint.PointerId] = touch;
//            }
//        }

//        #endregion

//        public override TouchCollection GetState()
//        {
//            View element = mElement;

//            if (!XamarinFormsHelper.IsViewVisible(mElement))
//            {
//                return EmptyTouchCollection;
//            }

//            Rectangle bounds = XamarinFormsHelper.GetAbsoluteBounds(element);
//            bounds.X *= mScaleFactor;
//            bounds.Y *= mScaleFactor;
//            bounds.Width *= mScaleFactor;
//            bounds.Height *= mScaleFactor;

//            s_releasedToRemove.Clear();

//            TouchLocation[] list = new TouchLocation[current.Count];
//            int i = -1;
//            foreach (var item in current)
//            {
//                // If pressed inside boundbox or or outside if move/invalid ect.
//                if (IsInsideBound(bounds, item.Value) || item.Value.State != TouchLocationState.Pressed)
//                {
//                    TouchLocation loc = item.Value;
//                    loc.X = loc.X * mScaleFactor - bounds.X;
//                    loc.Y = loc.Y * mScaleFactor - bounds.Y;
//                    list[++i] = loc;
//                }

//                current_hasBeenStated[item.Key] = true;

//                if (item.Value.State == TouchLocationState.Released)
//                {
//                    s_releasedToRemove.Add(item.Key);
//                }
//                else if (item.Value.MouseWheel != 0.0) // Remove mouse wheel.
//                {
//                    s_releasedToRemove.Add(item.Key);
//                }
//            }

//            // Remove released touches.
//            for (i = s_releasedToRemove.Count - 1; i >= 0; i--)
//            {
//                current.Remove(s_releasedToRemove[i]);
//                current_hasBeenStated.Remove(s_releasedToRemove[i]);
//            }

//            return new TouchCollection(list);
//        }

//        private bool IsInsideBound(Vector4 bounds, TouchLocation location)
//        {
//            if (location.X >= bounds.X1 && location.X <= bounds.X2 &&
//                location.Y >= bounds.Y1 && location.Y <= bounds.Y2)
//            {
//                return true;
//            }

//            return false;
//        }
//    }
//}
